﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;

namespace Dotnet.Utils.Utility.Config
{
    /// <summary>
    /// 应用程序配置扩展方法
    /// </summary>
    public static class AppSettingsServiceCollectionExtensions
    {
        /// <summary>
        /// 增加应用程序配置
        /// </summary>
        /// <typeparam name="TSettingRoot">配置类型</typeparam>
        /// <param name="services">服务集合</param>
        /// <param name="configuration">配置</param>
        /// <param name="assemblies">程序集合</param>
        /// <returns></returns>
        public static IServiceCollection AddAppSettings<TSettingRoot>(this IServiceCollection services, IConfiguration configuration) where TSettingRoot : class, new()
        {
            //应用配置注入
            services.Configure<TSettingRoot>(configuration);
            services.AddSingleton(provider =>
            {
                return provider.GetService<IOptions<TSettingRoot>>().Value;
            });

            //应用配置节点挨个注入
            services.AddAppSettingSections(typeof(TSettingRoot));

            return services;
        }

        /// <summary>
        /// 增加应用配置节点
        /// </summary>
        /// <param name="services"></param>
        /// <param name="parentType"></param>
        /// <returns></returns>
        private static void AddAppSettingSections(this IServiceCollection services, Type parentType)
        {
            //遍历主配置的所有属性
            foreach (var property in parentType.GetProperties())
            {
                //过滤掉简单类型
                if (property.PropertyType.IsValueType || property.PropertyType == typeof(string))
                {
                    continue;
                }

                //对象类型的单独注入
                services.AddSingleton(property.PropertyType, x =>
                {
                    var instance = x.GetService(parentType);
                    return property.GetValue(instance);
                });

                //递归
                services.AddAppSettingSections(property.PropertyType);
            }
        }
    }
}